home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / bbs / s342q07.lha / libmsg.c < prev    next >
C/C++ Source or Header  |  1994-07-02  |  11KB  |  429 lines

  1. /*
  2.  * *                            libmsg.c * * Common message handling
  3.  * functions for Citadel bulletin board system.
  4.  */
  5. /*
  6.  * *                            history * * 88Oct12 HAW  Generalize
  7.  * getMessage() * 87Feb11 HAW  Created.
  8.  */
  9. #include "ctdl.h"
  10. /*
  11.  * *                            contents * *    getMessage()            load
  12.  * message into RAM *   getMsgStr()             reads a string out of
  13.  * message.buf *        getMsgChar()            returns successive chars off
  14.  * disk *       startAt()               setup to read a message off disk *
  15.  * unGetMsgChar()               return a char to getMsgChar()
  16.  */
  17. struct mBuf mFile1,
  18.           mFile2;
  19. MessageBuffer msgBuf,
  20.           tempMess;
  21. FILE     *msgfl,
  22.          *msgfl2;
  23. static int GMCCache;
  24. extern CONFIG cfg;
  25.  
  26. /*
  27.  * * getMessage() * * This function reads a message off disk into RAM.  The
  28.  * source of the message * is controlled by the Source parameter; if the
  29.  * source is ctdlmsg.sys, then * a previous call to setUp has specified the
  30.  * message. * * FromNet - this indicates if the message is coming from a
  31.  * network-generated * temporary file (TRUE) or from ctdlmsg.sys (FALSE).
  32.  * If the latter then this * function must find the start of message within
  33.  * the current sector.  Also, * the 'w' field of messages has different
  34.  * meanings depending on the source of * the message (messy, but useful). *
  35.  * * all - TRUE indicates the message text should be read in, FALSE
  36.  * indicates * reading should end when the 'M' field is encountered. * *
  37.  * ClearOthers - indicates all lists associated with msgBuf should be
  38.  * cleared * before the message is read in.
  39.  */
  40. char
  41. getMessage(int (*Source) (void), char FromNet, char all, char ClearOthers)
  42. {
  43.   int       c;
  44.   char      CC[CC_SIZE],
  45.            *d;
  46.  
  47. /*
  48.  * clear msgBuf out
  49.  */
  50.   if (ClearOthers)
  51.     ZeroMsgBuffer(&msgBuf);
  52.   if (!FromNet)
  53.     {
  54.  /*
  55.   * only do this for messages from our own msgs
  56.   */
  57.       do
  58.     {
  59.       c = getMsgChar();
  60.  
  61.     }
  62.       while (c != 0xFF);    /*
  63.                  * find start of msg
  64.                  */
  65.       msgBuf.mbheadChar = mFile1.oldChar;    /*
  66.                          * record location
  67.                          */
  68.       msgBuf.mbheadSector = mFile1.oldSector;
  69.       getMsgStr(getMsgChar, msgBuf.mbId, NAMESIZE);
  70.     }
  71.   do
  72.     {
  73.       c = (*Source) ();
  74.       switch (c)
  75.     {
  76.       case 'A':
  77.         getMsgStr(Source, msgBuf.mbauth, sizeof msgBuf.mbauth);
  78.         break;
  79.       case 'D':
  80.         getMsgStr(Source, msgBuf.mbdate, NAMESIZE);
  81.         break;
  82.       case 'C':
  83.         getMsgStr(Source, msgBuf.mbtime, NAMESIZE);
  84.         break;
  85.       case 'M':    /*
  86.              * just exit -- we'll read off disk
  87.              */
  88.         break;
  89.       case 'N':
  90.         getMsgStr(Source, msgBuf.mboname, NAMESIZE);
  91.         while ((d = strchr(msgBuf.mboname, '_')) != NULL)
  92.           *d = ' ';
  93.         break;
  94.       case 'O':
  95.         getMsgStr(Source, msgBuf.mborig, NAMESIZE);
  96.         break;
  97.       case 'R':
  98.         getMsgStr(Source, msgBuf.mbroom, NAMESIZE);
  99.         break;
  100.       case 'S':
  101.         getMsgStr(Source, msgBuf.mbsrcId, NAMESIZE);
  102.         break;
  103.       case 'T':
  104.         getMsgStr(Source, msgBuf.mbto, sizeof msgBuf.mbto);
  105.         break;
  106.       case 'Q':
  107.         getMsgStr(Source, msgBuf.mbaddr, sizeof msgBuf.mbaddr);
  108.         break;
  109.       case 'X':
  110.         getMsgStr(Source, msgBuf.mbdomain, NAMESIZE);
  111.         break;
  112.       case 'P':
  113.         getMsgStr(Source, msgBuf.mbOther, O_NET_PATH_SIZE);
  114.         break;
  115.       case 'W':
  116.         getMsgStr(Source, CC, CC_SIZE);
  117.         if (ClearOthers)
  118.           AddData(&msgBuf.mbCC, strdup(CC), NULL, FALSE);
  119.         break;
  120.       case 'w':
  121.         if (FromNet)
  122.           {
  123.         getMsgStr(Source, CC, CC_SIZE);
  124.         if (ClearOthers)
  125.           AddData(&msgBuf.mbOverride, strdup(CC), NULL, FALSE);
  126.  
  127.           }
  128.         else
  129.           {
  130.        /*
  131.         * now we can overload this -- 'w' is net only
  132.         */
  133.         getMsgStr(Source, msgBuf.mbreply, NAMESIZE);
  134.  
  135.           }
  136.         break;
  137.        /*
  138.         * yes, this is correct - we're overloading mbaddr.
  139.         */
  140.       case 't':
  141.         getMsgStr(Source, msgBuf.mbaddr, sizeof msgBuf.mbaddr);
  142.         break;
  143.       case -1:
  144.         return FALSE;
  145.       default:
  146.         if (isprint(c))
  147.           {
  148.        /*
  149.         * save foreign fields
  150.         */
  151.         msgBuf.mbtext[0] = c;
  152.         getMsgStr(Source, msgBuf.mbtext + 1, MAXTEXT - 5);
  153.         AddData(&msgBuf.mbForeign, strdup(msgBuf.mbtext), NULL, FALSE);
  154.         msgBuf.mbtext[0] = '\0';
  155.  
  156.           }
  157.         else if (c == 0xFF && !FromNet)
  158.           {
  159.        /*
  160.         * Damaged msgBase
  161.         */
  162.         unGetMsgChar(c);
  163.  
  164.           }
  165.         break;
  166.  
  167.     }
  168.  
  169.     }
  170.   while (c != 'M' && isprint(c));
  171.   if (c == 'M')
  172.     {
  173.       if (all)
  174.     getMsgStr(Source, msgBuf.mbtext, MAXTEXT);
  175.       return TRUE;
  176.  
  177.     }
  178.   return FALSE;
  179.  
  180. }
  181. /*
  182.  * * getMsgStr() * * This function reads a string from the given source.
  183.  */
  184. void
  185. getMsgStr(int (*Source) (void), char *dest, int lim)
  186. {
  187.   int       c;
  188.  
  189.   while ((c = (*Source) ()) && c != EOF)
  190.     {
  191.  /*
  192.   * read the complete string
  193.   */
  194.       if (lim)
  195.     {
  196.      /*
  197.       * if we have room then
  198.       */
  199.       lim--;
  200.       if (c == '\r')
  201.         c = '\n';
  202.       *dest++ = c;    /*
  203.              * copy char to buffer
  204.              */
  205.  
  206.     }
  207.  
  208.     }
  209.   if (!lim)
  210.     dest--;    /*
  211.          * Ensure not overwrite next door neighbor
  212.          */
  213.   *dest = '\0';        /*
  214.              * tie string off with null
  215.              */
  216.  
  217. }
  218. /*
  219.  * * getMsgChar() * * This function returns sequential chars from
  220.  * CtdlMsg.Sys.
  221.  */
  222. int
  223. getMsgChar()
  224. {
  225.   long      work;
  226.   int       toReturn;
  227.  
  228.   if (GMCCache)
  229.     {
  230.  /*
  231.   * someone did an unGetMsgChar() --return it
  232.   */
  233.       toReturn = GMCCache;
  234.       GMCCache = '\0';
  235.       return (toReturn & 0xFF);
  236.  
  237.     }
  238.   mFile1.oldChar = mFile1.thisChar;
  239.   mFile1.oldSector = mFile1.thisSector;
  240.   toReturn = mFile1.sectBuf[mFile1.thisChar];
  241.   toReturn &= 0xFF;    /*
  242.              * Only want the lower 8 bits
  243.              */
  244.   mFile1.thisChar = ++mFile1.thisChar % MSG_SECT_SIZE;
  245.   if (mFile1.thisChar == 0)
  246.     {
  247.  /*
  248.   * time to read next sector in:
  249.   */
  250.       mFile1.thisSector = ++mFile1.thisSector % cfg.maxMSector;
  251.       work = mFile1.thisSector;
  252.       work *= MSG_SECT_SIZE;
  253.       fseek(msgfl, work, 0);
  254.       if (fread(mFile1.sectBuf, MSG_SECT_SIZE, 1, msgfl) != 1)
  255.     {
  256.       crashout("?nextMsgChar-read fail");
  257.  
  258.     }
  259.       crypte(mFile1.sectBuf, MSG_SECT_SIZE, 0);
  260.  
  261.     }
  262.   return (toReturn);
  263.  
  264. }
  265. /*
  266.  * * startAt() * * This function sets the location to begin reading a
  267.  * message from. This is * usually only the sector, since byte offset within
  268.  * the sector is not * saved.
  269.  */
  270. void
  271. startAt(FILE * whichmsg, struct mBuf *mFile, SECTOR_ID sect, int byt)
  272. {
  273.   long      temp;
  274.  
  275.   GMCCache = '\0';    /*
  276.              * cache to unGetMsgChar() into
  277.              */
  278.   if (sect >= cfg.maxMSector)
  279.     {
  280.       printf("?startAt s=%u,b=%d", sect, byt);
  281.       return;    /*
  282.          * Don't crash anymore, just skip the msg
  283.          */
  284.  
  285.     }
  286.   mFile->thisChar = byt;
  287.   mFile->thisSector = sect;
  288.   temp = sect;
  289.   temp *= MSG_SECT_SIZE;
  290.   fseek(whichmsg, temp, 0);
  291.   if (fread(mFile->sectBuf, MSG_SECT_SIZE, 1, whichmsg) != 1)
  292.     {
  293.       crashout("?startAt read fail");
  294.  
  295.     }
  296.   crypte(mFile->sectBuf, MSG_SECT_SIZE, 0);
  297.  
  298. }
  299. /*
  300.  * * unGetMsgChar() * * This function returns (at most one) char to
  301.  * getMsgChar().
  302.  */
  303. void
  304. unGetMsgChar(char c)
  305. {
  306.   GMCCache = (int) c;
  307.  
  308. }
  309. /*
  310.  * * ZeroMsgBuffer() * * This function zeroes a message buffer.  This
  311.  * includes clearing lists out * legally, etc.
  312.  */
  313. void
  314. ZeroMsgBuffer(MessageBuffer * msg)
  315. {
  316.   memset(msg, 0, STATIC_MSG_SIZE);
  317.   KillList(&msg->mbCC);
  318.   KillList(&msg->mbOverride);
  319.   KillList(&msg->mbForeign);
  320.   msg->mbtext[0] = 0;
  321. }
  322. /*
  323.  * * InitMsgBase() * * This function opens the msg base(s), inits the msg
  324.  * buffers.
  325.  */
  326. void
  327. InitMsgBase()
  328. {
  329.   SYS_FILE  name;
  330.  
  331.   makeSysName(name, "ctdlmsg.sys", &cfg.msgArea);
  332.   openFile(name, &msgfl);
  333.   if (cfg.BoolFlags.mirror)
  334.     {
  335.       makeSysName(name, "ctdlmsg.sys", &cfg.msg2Area);
  336.       openFile(name, &msgfl2);
  337.  
  338.     }
  339.   InitBuffers();
  340.  
  341. }
  342. /*
  343.  * * InitBuffers() * * This function initializes the message buffers.
  344.  */
  345. void
  346. InitBuffers()
  347. {
  348.   static SListBase MsgBase =
  349.   {
  350.     NULL, ChkCC, NULL, free, strdup
  351.  
  352.   };
  353.  
  354.   copy_struct(MsgBase, msgBuf.mbCC);
  355.   copy_struct(MsgBase, msgBuf.mbOverride);
  356.   copy_struct(MsgBase, msgBuf.mbInternal);
  357.   copy_struct(MsgBase, msgBuf.mbForeign);
  358.   copy_struct(MsgBase, tempMess.mbOverride);
  359.   copy_struct(MsgBase, tempMess.mbCC);
  360.   copy_struct(MsgBase, tempMess.mbInternal);
  361.   copy_struct(MsgBase, tempMess.mbForeign);
  362.   msgBuf.mbtext = GetDynamic(MAXTEXT);
  363.   tempMess.mbtext = GetDynamic(MAXTEXT);
  364.  
  365. }
  366. /*
  367.  * * findMessage() * * This function will get all set up to do something
  368.  * with a message.
  369.  */
  370. char
  371. findMessage(SECTOR_ID loc, MSG_NUMBER id, char ClearOthers)
  372. {
  373.   MSG_NUMBER here;
  374.  
  375.   id &= S_MSG_MASK;
  376.   startAt(msgfl, &mFile1, loc, 0);
  377.   do
  378.     {
  379.       getMessage(getMsgChar, FALSE, FALSE, ClearOthers);
  380.       here = atol(msgBuf.mbId);
  381.     }
  382.   while (here != id && mFile1.thisSector == loc);
  383.   if (here != id)
  384.     mPrintf("Ooops, couldn't find %ld @ %d.\n ", id, loc);
  385.   return (char) ((here == id));
  386.  
  387. }
  388. /*
  389.  * * Preliminary comments & code for CC feature in C-86. * * Comments and
  390.  * notes. * * o Numerous requests for this feature tend to make it valuable.
  391.  * * * o Suggest we have a field which may have multiple instances in any
  392.  * message. *   This is the 'cc' field.  Suggest further that it be 2 *
  393.  * NAMESIZE bytes *   long in order to allow node designators. * * o
  394.  * Implementation: The getMessage() function should build a linked list *
  395.  * (possibly generic list: libarch.c) as it reads in a message of each *   CC
  396.  * recipient.  Will need to have a disposal function for this list as *
  397.  * each message is disposed of.  May take a little code massage to make *
  398.  * sure we hit all the high points. * * o Only available for Mail>. * o
  399.  * (Since getMessage handles all the forms of getting messages from any *
  400.  * source, this handles all the net forms, too.) * * o Code massage points
  401.  * not otherwise covered in this file: *   - Held Messages. *   - Interrupted
  402.  * Messages(!). *   - getMessage(). *   - putMessage() - how do we handle the
  403.  * analog to noteMessage()?  New *     parameter? * * o Network provisions *
  404.  *  - Net support not present for this type of message. *   - New field, net
  405.  * only: Recipient override.  Indicates who mail is to be *     given access
  406.  * to this message, may (easily) exclude recipient specified *     in the
  407.  * mbto[] field.  New field named mboverride[NAMESIZE * 2]. *   - Like mbCC,
  408.  * should be handled as list with multiple instances. *   - Check for mail
  409.  * should check this list instead of mbto iff mboverride *     is present. *
  410.  *  - mboverride fields will not contain node designators (initially). *
  411.  * mbCC fields will, where necessary. * * o Other comments and thoughts about
  412.  * design, etc. *   - Unlogged users should not have access. *   - List of CC
  413.  * users should be accessible to message writer. *   - Able to remove someone
  414.  * from list of CC users??? *   - Net designation.  Use STadel's '@'
  415.  * convention?  Seems logical. *   - NEED FORMAT FOR DISPLAY OF FINISHED &
  416.  * DELIVERED MESSAGE! *   - NETHACK3.MAN will need updating. *   - * * ALSO
  417.  * SEE CC.C.
  418.  */
  419. /*
  420.  * * ChkCC() * * This will see if the two records are identical.  This is
  421.  * used for list * searches.
  422.  */
  423. void     *
  424. ChkCC(char *d1, char *d2)
  425. {
  426.   return (strCmpU(d1, d2) == SAMESTRING) ? d1 : NULL;
  427.  
  428. }
  429.